﻿// NFakeMail - A fake SMTP Server for software testing.
// 
// Copyright (C) 2010, João Angelo
// 
// This file is part of NFakeMail.
//
// NFakeMail is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// 
// NFakeMail is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with NFakeMail; if not, see <http://www.gnu.org/licenses/>.

namespace NFakeMail.Runner
{
    using System;
    using System.Diagnostics;
    using System.Reflection;
    using Helpers.CommandLine.Parser;

    /// <summary>
    /// NFakeMail Runner application.
    /// </summary>
    /// <author> jmangelo </author>
    /// <history>
    /// ______________________________________________________________________________________
    /// History :
    /// 20100816 [+] jmangelo     Initial version
    /// ______________________________________________________________________________________
    /// </history>
    internal class Program
    {
        private static FakeSmtpServer FakeSmtpServer { get; set; }

        private static Version AssemblyVersion
        {
            get
            {
                return Assembly.GetExecutingAssembly().GetName().Version;
            }
        }

        private static string AssemblyConfiguration
        {
            get
            {
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(
                    typeof(AssemblyConfigurationAttribute), 
                    false);

                if (attributes.Length == 0)
                {
                    return string.Empty;
                }

                return ((AssemblyConfigurationAttribute)attributes[0]).Configuration;
            }
        }

        private static void Main(string[] args)
        {
            PrintCopyrightDisclaimer();

            var commandLine = GetCommandLineParser().Parse(args);

            dynamic options = commandLine.Options.AsDynamic();

            int port = options.Port.Value;
            bool silent = options.Silent.Value;

            string outputPath = Environment.CurrentDirectory;
            if (options.OutputPath.Available)
            {
                outputPath = options.OutputPath.Value;
            }

            Console.CancelKeyPress += Console_CancelKeyPress;

            OutputSink output;

            if (silent)
            {
                output = new FileSystemOutputSink(outputPath);
            }
            else
            {
                output = OutputSink.Chain(new ConsoleOutputSink(), new FileSystemOutputSink(outputPath));
            }

            FakeSmtpServer = new FakeSmtpServer(output, port);

            Process.GetCurrentProcess().WaitForExit();
        }

        private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
        {
            if (FakeSmtpServer != null)
            {
                FakeSmtpServer.Dispose();
            }
        }

        private static CommandLineParser GetCommandLineParser()
        {
            var parser = new CommandLineParser { PrintUsageInfoOnError = true };

            parser.ReservedCommands.Add(new ReservedCommand("-warranty", ExitWithWarrantyInfo));
            parser.ReservedCommands.Add(new ReservedCommand("-conditions", ExitWithConditionsInfo));

            OptionDefinition definition;

            definition = parser.ExpectSingle("port", "p");
            definition.DataType = OptionDataType.Int32;
            definition.DefaultValue = 10025;
            definition.Description = "Specifies the local port for the SMTP server to listen for requests.";

            definition = parser.AcceptFlag("silent", "s");
            definition.Description = "Specifies if the application should not output information.";

            definition = parser.AcceptSingle("outputPath", "o");
            definition.Description = "Specifies the path where the mail messages will be stored.";

            return parser;
        }

        private static void PrintCopyrightDisclaimer()
        {
            string version = String.Format(
                "{0}.{1} {2}", 
                AssemblyVersion.Major, 
                AssemblyVersion.Minor, 
                AssemblyConfiguration);

            version = version.TrimEnd();

            Console.WriteLine("NFakeMail version {0}, Copyright (C) 2010, João Angelo.", version);
            Console.WriteLine();
            Console.WriteLine("NFakeMail comes with ABSOLUTELY NO WARRANTY; for details use");
            Console.WriteLine("option '-warranty'.  This is free software, and you are welcome");
            Console.WriteLine("to redistribute it under certain conditions; use option '-conditions'");
            Console.WriteLine("for details.");
            Console.WriteLine();
        }

        private static void ExitWithWarrantyInfo()
        {
            Console.WriteLine("NFakeMail Warranty Information:");
            Console.WriteLine();
            Console.WriteLine("NFakeMail is distributed in the hope that it will be useful,");
            Console.WriteLine("but WITHOUT ANY WARRANTY; without even the implied warranty of");
            Console.WriteLine("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the");
            Console.WriteLine("GNU General Public License for more details.");
            Console.WriteLine();

            Environment.Exit(0);
        }

        private static void ExitWithConditionsInfo()
        {
            Console.WriteLine("NFakeMail Distribution Information:");
            Console.WriteLine();
            Console.WriteLine("NFakeMail is free software; you can redistribute it and/or");
            Console.WriteLine("modify it under the terms of the GNU General Public License");
            Console.WriteLine("as published by the Free Software Foundation; either version 2");
            Console.WriteLine("of the License, or (at your option) any later version.");
            Console.WriteLine();

            Environment.Exit(0);
        }
    }
}
